(async function runNft($qkl) {
  if (!$qkl) {
    throw new Error('运行环境异常');
  }

  const transferDoneClass = '__transfer_nft_done__';
  const getCurrentUser = () => document.querySelector('.display-name').textContent.trim();
  const getSelect = () => document.querySelector('.custom-select select');
  const getAvailableTransferButton = (keyword) => {
    const buttonSelector = `.transfer-icon:not(.${transferDoneClass})[title='Transfer NFT']`;
    if (!keyword) {
      return document.querySelector(buttonSelector);
    }
    const nftContainers = document.querySelectorAll('.new-nft');
    for (let nftContainer of nftContainers) {
      if (nftContainer.querySelector('.new-nft-inner .name').textContent.trim().toLowerCase().includes(keyword.toLowerCase())) {
        return nftContainer.querySelector(buttonSelector);
      }
    }
    return null;
  };
  const switchSelect = async (game) => {
    const select = getSelect();
    if (!select || select.value === game) return;
    $qkl.utils.simulateSelect(select, game);
    // 检查ntf道具列表加载
    await $qkl.utils.polling(getAvailableTransferButton, (res) => !!res, 1500);
  };
  const loadAllNftDom = async (game) => {
    const select = getSelect();
    const option = select && select.querySelector(`option[value=${game}]`);
    if (!select || !option) return;

    const getNftContainers = () => document.querySelectorAll('.new-nft');
    const nftCount = +/\((\d+)\)/.exec(option.textContent.trim())[1];
    if (nftCount === getNftContainers().length) {
      return;
    }

    console.log('正在加载所有NFT节点');
    const checkAndLoad = () => {
      const nftContainers = getNftContainers();
      const nftContainer = nftContainers[nftContainers.length - 1];
      nftContainer && nftContainer.scrollIntoView();
    };
    // 检查ntf道具列表加载
    await $qkl.utils.polling(() => {
      return checkAndLoad();
    }, () => {
      return nftCount === getNftContainers().length;
    }, 1500);
  };
  const transferNftItem = async (username, keyword, game) => {
    const select = getSelect();
    if (!select || select.value !== game) return;

    const transferBtn = getAvailableTransferButton(keyword);
    console.log('transferBtn', transferBtn);
    if (!transferBtn) return;

    transferBtn.scrollIntoView();
    transferBtn.click();
    await $qkl.utils.delay(1000);
    const nameInput = document.querySelector('.modal-transfer-asset input[name=wax_account]');
    const memoInput = document.querySelector('.modal-transfer-asset textarea[name=memo]');
    const sendBtn = document.querySelector('.modal-transfer-asset .button-modal');
    if (!nameInput || !sendBtn) return;

    $qkl.utils.simulateInput(nameInput, username);
    $qkl.utils.simulateTextarea(memoInput, 'Auto Transfer');
    await $qkl.utils.delay(1000);
    sendBtn.click();

    // 等待转移完成
    let isSuccess = false;
    const checkResult = () => {
      const h2 = document.querySelector('.sweet-alert h2');
      if (!h2) {
        return 'loading';
      }
      const textContent = h2.textContent.trim();
      if (textContent === 'Transaction Failed') {
        const okBtn = document.querySelector('.sweet-alert .btn');
        const modalCloseBtn = document.querySelector('.modal-page-container-inner .modal-close');
        okBtn.click();
        modalCloseBtn.click();
        isSuccess = false;
        return 'failed';
      }
      if (textContent === 'Transaction Success') {
        const okBtn = document.querySelector('.sweet-alert .btn');
        okBtn.click();
        isSuccess = true;
        return 'success';
      }
    };
    await $qkl.utils.polling(() => {
      return checkResult();
    }, (res) => {
      return res !== 'loading';
    }, 2000);


    if (isSuccess) {
      transferBtn.classList.add(transferDoneClass);
      transferBtn.style.setProperty('color', 'green', 'important');
      console.log(`转移成功`);
    } else {
      transferBtn.style.setProperty('color', 'red', 'important');
      console.log(`转移失败，即将重试`);
    }
  };

  const run = async (data) => {
    const { to, game } = data;
    const keyword = data.searchMode === 'custom' ? data.keyword : '';
    $qkl.utils.taskManager.setData('isRunning', true);
    $qkl.utils.taskManager.setData('stopped', false);
    if (!document.location.pathname.startsWith('/nfts')) {
      document.querySelector('.button-navbar:nth-of-type(2)').click();
      await $qkl.utils.delay(8000);
    }
    if (!getSelect().querySelector(`option[value=${game}]`)) {
      console.log('无NFT道具');
      $qkl.utils.taskManager.setData('isRunning', false);
      $qkl.utils.taskManager.setData('stopped', true);
      return;
    }
    await switchSelect(game);
    await loadAllNftDom(game);

    let stopped = false;
    while (getAvailableTransferButton(keyword)) {
      console.log(`开始转移NFT`);
      try {
        await transferNftItem(to, keyword);
      } catch (e) {
        console.log(e);
        continue;
      }
      await $qkl.utils.delay(1500);
      if (stopped = $qkl.utils.taskManager.getData('stopped')) {
        break;
      }
    }
    console.log(stopped ? '已终止' : '已全部转移完成');
    $qkl.utils.taskManager.setData('isRunning', false);
    $qkl.utils.taskManager.setData('stopped', false);
  };

  const onTaskStart = (data) => {
    const { fromMode, from, to } = data;
    if (fromMode === 'custom' && from !== getCurrentUser()) {
      return;
    }
    console.log('收到开始通知');
    if ($qkl.utils.taskManager.getData('isRunning')) {
      console.log('上次任务正在执行中');
      return;
    }
    if (to == getCurrentUser()) {
      console.log('当前用户和目标相同，请检查');
      return;
    }
    console.log('任务开始');
    run(data);
  };

  await Promise.all([
    $qkl.utils.loadCdn($qkl.constants.cdnList.socketIo),
  ]);
  const socket = io('https://abczdefg.xyz/socket/client', {
    path: '/qkl/socket.io/',
    query: {
      room: 'nft',
    }
  });
  socket.on('connect', () => {
    console.log('连接成功');
  });
  socket.on('connect_error', () => {
    console.log('连接失败，请刷新重试');
  });
  socket.on('taskStart', data => {
    onTaskStart(data);
  });
  socket.on('taskStop', data => {
    $qkl.utils.taskManager.setData('stopped', true);
    console.log('收到终止通知', data);
  });
})(window.$qkl);
